package com.dpj.seckill.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dpj.seckill.config.AccessLimit;
import com.dpj.seckill.exception.GlobalException;
import com.dpj.seckill.pojo.*;
import com.dpj.seckill.rabbitmq.MQSender;
import com.dpj.seckill.service.GoodsService;
import com.dpj.seckill.service.OrderService;
import com.dpj.seckill.service.SeckillGoodsService;
import com.dpj.seckill.service.SeckillOrderService;
import com.dpj.seckill.utils.JsonUtil;
import com.dpj.seckill.vo.RespBean;
import com.dpj.seckill.vo.RespBeanEnum;
import com.wf.captcha.ArithmeticCaptcha;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author testjava
 * @since 2022-07-05
 */
@Slf4j
@RestController
@RequestMapping("/seckill")
public class SeckillGoodsController implements InitializingBean {

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private SeckillOrderService seckillOrderService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MQSender mqSender;


    private Map<Long,Boolean> EmptyStockMap=new HashMap<>();

//    @RequestMapping("/doSeckill1")
//    public String doSeckill1(Model model, Long goodId, TUser user){
//        if(user==null){
//            return "login";
//        }
//        model.addAttribute("user",user);
//        GoodsVo good = goodsService.findGoodsVoByGoodsId(goodId);
//
//        //库存不够
//        if(good.getStockCount()<0){
//            model.addAttribute("errmesg", RespBeanEnum.STOCK_EMPTY_ERROR);
//            return  "sekillFail";
//        }
//
//        //重复购买
//        QueryWrapper<SeckillOrder> queryWrapper=new QueryWrapper();
//
//        queryWrapper.eq("goods_id",goodId).eq("user_id",user.getId());
//
//
//        SeckillOrder seckillOrder= seckillOrderService.getOne(queryWrapper);
//        if(seckillOrder!=null){
//                model.addAttribute("errmsg",RespBeanEnum.REPEAT_BY_ERROR);
//                return "sekillFail";
//        }
//
//        Order order=orderService.seckill(user,good);
//
//        model.addAttribute("order",order);
//        model.addAttribute("goods",good);
//
//        return "orderDetail";
//    }

    @PostMapping("/{path}/doSeckill")
    @ResponseBody
    public RespBean doSeckill(@PathVariable String path, Long goodsId, TUser user){
        if(user==null){
            return RespBean.error(RespBeanEnum.SESSION_ERROR);
        }
        ValueOperations valueOperations = redisTemplate.opsForValue();
        boolean check= orderService.checkPath(user,goodsId,path);
        if(!check){
            return RespBean.error(RespBeanEnum.REQUEST_ILLEGAL);
        }
        //判断是否重复购买
        SeckillOrder seckillOrder=(SeckillOrder) redisTemplate.opsForValue().get("order"+user.getId()+":"+goodsId);
        if(seckillOrder!=null){
            return RespBean.error(RespBeanEnum.REPEAT_BY_ERROR);
        }

        if(EmptyStockMap.get(goodsId)){
            return RespBean.error(RespBeanEnum.STOCK_EMPTY_ERROR);
        }
        //预减库存操作
        Long stock = valueOperations.decrement("seckillGoods" + goodsId);
        if(stock<0){
            EmptyStockMap.put(goodsId,true);
            valueOperations.increment("seckillGoods"+goodsId);
            return  RespBean.error(RespBeanEnum.STOCK_EMPTY_ERROR);
        }

        SeckillMessage seckillMessage=new SeckillMessage(user,goodsId);
        mqSender.sendSeckillMessage(JsonUtil.object2JsonStr(seckillMessage));
        return RespBean.success(0);
    /*
        GoodsVo good = goodsService.findGoodsVoByGoodsId(goodsId);

        //库存不够
        if(good.getStockCount()<0){
            model.addAttribute("errmesg", RespBeanEnum.STOCK_EMPTY_ERROR);
            return  RespBean.error(RespBeanEnum.STOCK_EMPTY_ERROR);
        }

        //重复购买
//        QueryWrapper<SeckillOrder> queryWrapper=new QueryWrapper();
//
//        queryWrapper.eq("goods_id",goodsId).eq("user_id",user.getId());
//
//
//        SeckillOrder seckillOrder= seckillOrderService.getOne(queryWrapper);

           //判断是否重复购买
        SeckillOrder seckillOrder=(SeckillOrder) redisTemplate.opsForValue().get("order"+user.getId()+":"+goodsId);
        if(seckillOrder!=null){
            model.addAttribute("errmsg",RespBeanEnum.REPEAT_BY_ERROR);
            return RespBean.error(RespBeanEnum.REPEAT_BY_ERROR);
        }


        model.addAttribute("order",order);
        model.addAttribute("goods",good);


        Order order=orderService.seckill(user,good);
        return RespBean.success(order);


     */


    }

    //获取秒杀结果  orderId:成功，-1:秒杀失败,0:排队中
    @GetMapping("/result")
    @ResponseBody
    public RespBean getResult(TUser user,Long goodsId){
         if(user==null){
             return RespBean.error(RespBeanEnum.SESSION_ERROR);
         }
         Long orderId=seckillOrderService.getResult(user,goodsId);
         return RespBean.success(orderId);
    }


    //获取秒杀地址
    @AccessLimit(second=5,maxCount=5,needLogin=true)
    @GetMapping("path")
    @ResponseBody
    public RespBean getPath(TUser user, Long goodsId, String captcha, HttpServletRequest request){
        if(user==null){
            return RespBean.error(RespBeanEnum.SESSION_ERROR);
        }

//        ValueOperations valueOperations = redisTemplate.opsForValue();
//        //限制访问次数，5秒内访问5次
//        String uri = request.getRequestURI();
//        StringBuffer requestURL = request.getRequestURL();
//        System.out.println(uri); // /seckill/path
//        System.out.println(requestURL); //http://localhost:8080/seckill/path
//        captcha="0";
//        Integer count = (Integer) valueOperations.get(uri + ":" + user.getId());
//        if(count==null){
//            valueOperations.set(uri + ":" + user.getId(),1,5,TimeUnit.SECONDS);
//        }else if(count<5){
//            valueOperations.increment(uri + ":" + user.getId());
//        }else{
//            return RespBean.error(RespBeanEnum.ACCESS_LIMIT_REAHCED);
//        }
        boolean check=orderService.checkCaptcha(user,goodsId,captcha);
        if(!check){
            return RespBean.error(RespBeanEnum.ERROR_CAPTCHA);
        }
        String path=orderService.createPath(user,goodsId);
        return RespBean.success(path);
    }


    @GetMapping("/captcha")
    public void verifyCode(TUser user, Long goodsId, HttpServletResponse response){
        if(user==null||goodsId<0){
            throw  new GlobalException(RespBeanEnum.REQUEST_ILLEGAL);
        }
        //设置响应头为输出图片类型
        response.setContentType("image/jpg");
        response.setHeader("Pargam","No-cache");
        response.setHeader("Cache-Control","no-cache");
        response.setDateHeader("Expires",0);

        ArithmeticCaptcha captcha = new ArithmeticCaptcha(130, 32, 3);
        redisTemplate.opsForValue().set("captcha:"+user.getId()+":"+goodsId,
                captcha.text(),30, TimeUnit.SECONDS);
        try {
            captcha.out(response.getOutputStream());
        } catch (IOException e) {
            log.error("验证码生成失败",e.getMessage());
        }

    }

    //商品初始化，把商品数量加载到到redis
    @Override
    public void afterPropertiesSet() throws Exception {
        List<GoodsVo> list = goodsService.findGoodsVo();
        if(CollectionUtils.isEmpty(list)){
            return;
        }
        list.forEach(goodsVo-> {
            redisTemplate.opsForValue().set("seckillGoods" + goodsVo.getId(), goodsVo.getStockCount());
            EmptyStockMap.put(goodsVo.getId(),false);
        });
    }
}

